using System;
using OracleInternal.Common;
using OracleInternal.I18N;

namespace OracleInternal.Network
{
	internal class AnoCommunication
	{
		internal const int STRING_TYPE = 0;

		internal const int RAW_TYPE = 1;

		internal const int UB1_TYPE = 2;

		internal const int UB2_TYPE = 3;

		internal const int UB4_TYPE = 4;

		internal const int VERSION_TYPE = 5;

		internal const int STATUS_TYPE = 6;

		internal const int ARRAY_TYPE = 7;

		internal const int MIN_TYPE = 0;

		internal const int MAX_TYPE = 7;

		internal const int UB1_LENGTH = 1;

		internal const int UB2_LENGTH = 2;

		internal const int UB4_LENGTH = 4;

		internal const int VERSION_LENGTH = 4;

		internal const int STATUS_LENGTH = 2;

		internal const int NA_MAGIC_SIZE = 4;

		internal const long DEADBEEF = 3735928559L;

		internal const int NA_HEADER_SIZE = 13;

		internal const int ARRAY_PACKET_HEADER_LENGTH = 10;

		internal const int SERVICE_HEADER_LENGTH = 8;

		internal const int SUBPACKET_LENGTH = 4;

		internal const long NA_MAGIC = 3735928559L;

		internal const int VERSION = 11;

		internal const int RELEASE = 2;

		internal const int UPDATE = 0;

		internal const int PORT = 2;

		internal const int PORTUPDATE = 0;

		internal const short NO_ERROR = 0;

		internal SessionContext sessCtx;

		internal AnoCommunication(SessionContext sessCtx)
		{
			this.sessCtx = sessCtx;
		}

		internal long GetVersion()
		{
			return 186647040L;
		}

		internal void FlushData()
		{
			sessCtx.m_writerStream.Flush();
		}

		internal void SendUB1(short num)
		{
			SendPacketHeader(1, 2);
			sessCtx.m_writerStream.Write((byte)(0xFFu & (uint)num));
		}

		internal void SendUB2(int num)
		{
			SendPacketHeader(2, 3);
			WriteUB2(num);
		}

		internal void SendUB4(long num)
		{
			SendPacketHeader(4, 4);
			WriteUB4(num);
		}

		internal void SendUB2Array(int[] nArray)
		{
			int num = nArray.Length;
			SendPacketHeader(10 + num * 2, 1);
			WriteUB4(3735928559L);
			WriteUB2(3);
			WriteUB4(nArray.Length);
			for (int i = 0; i < num; i++)
			{
				WriteUB2(nArray[i] & 0xFFFF);
			}
		}

		internal void SendStatus(int status)
		{
			SendPacketHeader(2, 6);
			WriteUB2(status);
		}

		internal void SendVersion()
		{
			SendPacketHeader(4, 5);
			WriteUB4(GetVersion());
		}

		internal void SendString(string str)
		{
			SendPacketHeader(str.Length, 0);
			sessCtx.m_writerStream.Write(Conv.GetInstance(871).ConvertStringToBytes(str, 0, str.Length));
		}

		internal void SendRaw(byte[] rawData)
		{
			SendPacketHeader(rawData.Length, 1);
			sessCtx.m_writerStream.Write(rawData);
		}

		internal void SendPacketHeader(int length, int type)
		{
			ValidateType(length, type);
			WriteUB2(length);
			WriteUB2(type);
		}

		internal void WriteVersion()
		{
			WriteUB4(GetVersion());
		}

		internal void WriteUB1(short num)
		{
			sessCtx.m_writerStream.Write((byte)(0xFFu & (uint)num));
		}

		internal void WriteUB2(int num)
		{
			byte[] array = new byte[2];
			byte length = Value2Buffer((short)(0xFFFF & num), array);
			sessCtx.m_writerStream.Write(array, 0, length);
		}

		internal void WriteUB4(long num)
		{
			byte[] array = new byte[4];
			byte length = Value2Buffer((int)(0xFFFFFFFFu & num), array);
			sessCtx.m_writerStream.Write(array, 0, length);
		}

		internal byte Value2Buffer(int value, byte[] tmpBuffer)
		{
			byte result = 0;
			for (int num = tmpBuffer.Length - 1; num >= 0; num--)
			{
				tmpBuffer[result++] = (byte)HelperClass.URShift(value, (8 * num) & 0xFF);
			}
			return result;
		}

		internal short ReceiveUB1()
		{
			ReceivePacketHeader(2);
			return ReadUB1();
		}

		internal int ReceiveUB2()
		{
			ReceivePacketHeader(3);
			return ReadUB2() & 0xFFFF;
		}

		internal long ReceiveUB4()
		{
			ReceivePacketHeader(4);
			return ReadUB4();
		}

		internal int[] receiveUB2Array()
		{
			ReceivePacketHeader(1);
			long num = ReadUB4();
			int num2 = ReadUB2();
			long num3 = ReadUB4();
			int[] array = new int[(int)num3];
			if (num != 3735928559u || num2 != 3)
			{
				throw new NetworkException(-6310);
			}
			for (int i = 0; i < num3; i++)
			{
				array[i] = ReadUB2();
			}
			return array;
		}

		internal int ReceiveStatus()
		{
			ReceivePacketHeader(6);
			return ReadUB2();
		}

		internal long ReceiveVersion()
		{
			ReceivePacketHeader(5);
			return ReadUB4();
		}

		internal string ReceiveString()
		{
			int size = ReceivePacketHeader(0);
			byte[] array = ReceiveByteArray(size);
			return Conv.GetInstance(871).ConvertBytesToString(array, 0, array.Length);
		}

		internal byte[] ReceiveRaw()
		{
			int size = ReceivePacketHeader(1);
			return ReceiveByteArray(size);
		}

		internal short ReadUB1()
		{
			short num = 0;
			try
			{
				if ((num = (short)sessCtx.m_readerStream.ReadOne()) < 0)
				{
					throw new NetworkException(12637);
				}
				return num;
			}
			catch (Exception)
			{
				throw new NetworkException(1);
			}
		}

		internal int ReadUB2()
		{
			byte[] tmpBuffer = new byte[2];
			return (int)Buffer2Value(tmpBuffer) & 0xFFFF;
		}

		internal long ReadUB4()
		{
			byte[] tmpBuffer = new byte[4];
			return Buffer2Value(tmpBuffer);
		}

		internal byte[] ReceiveByteArray(int size)
		{
			byte[] array = new byte[size];
			try
			{
				if (sessCtx.m_readerStream.Read(array) < 0)
				{
					throw new NetworkException(12637);
				}
				return array;
			}
			catch (Exception)
			{
				throw new NetworkException(1);
			}
		}

		internal int ReceiveByteArray(byte[] buffer, int offset, int length)
		{
			int num = 0;
			try
			{
				if ((num = sessCtx.m_readerStream.Read(buffer, offset, length)) < 0)
				{
					throw new NetworkException(12637);
				}
				return num;
			}
			catch (Exception)
			{
				throw new NetworkException(1);
			}
		}

		internal int ReceivePacketHeader(int type)
		{
			int num = ReadUB2();
			int receivedType = ReadUB2();
			ValidateReceivedType(num, receivedType, type);
			return num;
		}

		internal void ValidateReceivedType(int length, int receivedType, int type)
		{
			if (receivedType < 0 || receivedType > 7)
			{
				throw new NetworkException(-6313);
			}
			if (receivedType != type)
			{
				throw new NetworkException(-6314);
			}
			switch (type)
			{
			case 2:
				if (length > 1)
				{
					throw new NetworkException(-6312);
				}
				break;
			case 3:
			case 6:
				if (length > 2)
				{
					throw new NetworkException(-6312);
				}
				break;
			case 4:
			case 5:
				if (length > 4)
				{
					throw new NetworkException(-6312);
				}
				break;
			case 7:
				if (length < 10)
				{
					throw new NetworkException(-6312);
				}
				break;
			default:
				throw new NetworkException(-6313);
			case 0:
			case 1:
				break;
			}
		}

		internal long Buffer2Value(byte[] tmpBuffer)
		{
			long num = 0L;
			try
			{
				if (sessCtx.m_readerStream.Read(tmpBuffer) < 0)
				{
					throw new NetworkException(12637);
				}
			}
			catch (Exception)
			{
				throw new NetworkException(12637);
			}
			for (int i = 0; i < tmpBuffer.Length; i++)
			{
				num |= (tmpBuffer[i] & 0xFF) << 8 * (tmpBuffer.Length - 1 - i);
			}
			return num & 0xFFFFFFFFu;
		}

		internal void ValidateType(int length, int type)
		{
			if (type < 0 || type > 7)
			{
				throw new NetworkException(-6313);
			}
			switch (type)
			{
			case 2:
				if (length > 1)
				{
					throw new NetworkException(-6312);
				}
				break;
			case 3:
			case 6:
				if (length > 2)
				{
					throw new NetworkException(-6312);
				}
				break;
			case 4:
			case 5:
				if (length > 4)
				{
					throw new NetworkException(-6312);
				}
				break;
			case 7:
				if (length < 10)
				{
					throw new NetworkException(-6312);
				}
				break;
			default:
				throw new NetworkException(-6313);
			case 0:
			case 1:
				break;
			}
		}
	}
}
